﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Text
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Text;

    /// <summary>Represents an ASCII character encoding of Unicode characters, see
    /// <a href="http://msdn.microsoft.com/en-us/library/system.text.asciiencoding.aspx">System.Text.ASCIIEncoding</a>.
    /// </summary>
    /// <remarks>On Windows Phone a call to <see cref="Encoding.GetEncoding">Encoding.GetEncoding("us-ascii")</see>
    /// throws <see cref="ArgumentException"/>.</remarks>
    /// <threadsafety static="true" instance="false"/>
    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ASCII", Justification = "This is the official name in the desktop framework.")]
    public sealed class ASCIIEncoding : Encoding
    {
        /// <summary>Initializes a new instance of the <see cref="ASCIIEncoding"/> class.</summary>
        public ASCIIEncoding()
        {
        }

        /// <summary>See <see cref="Encoding.GetMaxCharCount"/>.</summary>
        public sealed override int GetMaxCharCount(int byteCount)
        {
            return byteCount;
        }

        /// <summary>See <see cref="Encoding.GetMaxByteCount"/>.</summary>
        public sealed override int GetMaxByteCount(int charCount)
        {
            return charCount;
        }

        /// <summary>See <see cref="Encoding.GetChars(byte[], int, int, char[], int)"/>.</summary>
        /// <remarks>Bytes > 0x7F are decoded as '?'.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Validated with call to AssertValidRanges.")]
        public sealed override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
        {
            AssertValidRanges(bytes, byteIndex, chars, charIndex, byteCount, "byteCount");
            int pastEnd = byteIndex + byteCount;

            for (; byteIndex < pastEnd; ++byteIndex, ++charIndex)
            {
                byte currentByte = bytes[byteIndex];
                chars[charIndex] = currentByte > 0x7F ? '?' : (char)currentByte;
            }

            return byteCount;
        }

        /// <summary>See <see cref="Encoding.GetCharCount(byte[], int, int)"/>.</summary>
        public sealed override int GetCharCount(byte[] bytes, int index, int count)
        {
            BufferHelper.AssertValidRange(bytes, "bytes", index, "index", count, "count");
            return count;
        }

        /// <summary>See <see cref="Encoding.GetBytes(char[], int, int, byte[], int)"/>.</summary>
        /// <remarks>Characters with a code > 0x7F are encoded as '?'.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Validated with call to AssertValidRanges.")]
        public sealed override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
        {
            AssertValidRanges(bytes, byteIndex, chars, charIndex, charCount, "charCount");
            int pastEnd = charIndex + charCount;

            for (; charIndex < pastEnd; ++charIndex, ++byteIndex)
            {
                char character = chars[charIndex];
                bytes[byteIndex] = character > 0x7F ? (byte)'?' : (byte)character;
            }

            return charCount;
        }

        /// <summary>See <see cref="Encoding.GetByteCount(char[], int, int)"/>.</summary>
        public sealed override int GetByteCount(char[] chars, int index, int count)
        {
            BufferHelper.AssertValidRange(chars, "chars", index, "index", count, "count");
            return count;
        }

        /// <summary>See <see cref="Encoding.WebName"/>.</summary>
        public sealed override string WebName
        {
            get
            {
                return "us-ascii";
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private static void AssertValidRanges(
            byte[] bytes, int byteIndex, char[] chars, int charIndex, int count, string countName)
        {
            BufferHelper.AssertValidRange(bytes, "bytes", byteIndex, "byteIndex", count, countName);
            BufferHelper.AssertValidRange(chars, "chars", charIndex, "charIndex", count, countName);
        }
    }
}
